﻿namespace Jiubang.Tracer {
    using System;
    using System.Diagnostics;

    /// <summary>
    /// 执行时间跟踪
    /// </summary>
    internal class StopwatchTracer : PrefTracer {
        private const long MaxElapsed = short.MaxValue;
        private readonly Stopwatch stopwatch;
        private long elapsedMilliseconds;

        public StopwatchTracer(string name, ILogger logger) : this(name, logger, false) { }

        internal StopwatchTracer(string name, ILogger logger, bool lazyStart)
            : base(name, logger) {
            stopwatch = new Stopwatch();
            if (!lazyStart) {
                stopwatch.Start();
            }
        }

        /// <summary>
        /// 重置计数器
        /// </summary>
        public override void Reset() {
            stopwatch.Reset();
            elapsedMilliseconds = 0;
            stopwatch.Start();
        }

        /// <summary>
        /// 检查从启动、最近一次Reset或Check执行到当前位置测度数据是否超过期望值。
        /// 如是，将实际测量值与标签追加至Logger
        /// </summary>
        /// <param name="onLoggingCallback">实际测量值超过期望值时调用该回调方法获取标签</param>
        /// <param name="expectedDifference">期望差值。如当前值-重置值&gt;该值将被日志记录</param>
        /// <returns>返回执行时间</returns>
        public override short Check(OnLoggingCallback onLoggingCallback, short expectedDifference) {
            long lastElapsedMilliseconds = elapsedMilliseconds;
            elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
            short elapsed = (short)Math.Min(MaxElapsed, elapsedMilliseconds - lastElapsedMilliseconds);

            if (elapsed >= expectedDifference) {
                Logger.Log(this, "ET:" + onLoggingCallback(), expectedDifference, elapsed);
            }
            return elapsed;
        }
    }
}